
#pragma once

#include "Char.h"

namespace Pan
{

    /**
     * @brief 字符串常量类
     */
    class StringConst
    {

    public:
        /**
         * @brief 解析十进制无符号整数
         * @param str 待解析的字符串
         * @param pnumber 保存解析结果的变量的指针
         * @return 成功解析的字符数
         */
        static unsigned int parse_unsigned_decimal_number(const wchar_t *str, unsigned long long *pnumber);

    protected:
        /**
         * @brief 一个指针变量的引用
         */
        const wchar_t *_p;

        // 构造与析构
    public:
        inline StringConst(const wchar_t *p = L"") : _p(p) {}
        inline StringConst(const StringConst &s) : _p(s._p) {}
        inline StringConst(StringConst &&s) : _p(s._p) {}
        inline ~StringConst() {}

    public:
        inline const wchar_t *pointer() const { return this->_p; }

    public:
        /**
         * @brief 计算字符串的长度，
         * 请确保保存字符串的字符数组中含有字符串结束符。
         * @return 字符串的长度
         */
        unsigned long calc_length() const;

    public:
        /**
         * @brief 计算字符串所占用的内存（字节数）
         *  注意：也包含字符串结束符占用的内存
         * @return 占用的字节数
         */
        unsigned long calc_bytes() const { return (this->calc_length() + 1) * sizeof(wchar_t); }

    public:
        /**
         * @brief 获取指定位置的字符
         * @param index 下标索引
         * @return 字符
         */
        inline wchar_t char_at(unsigned int index) const { return this->_p[index]; }

    public:
        inline Char char_at2(unsigned int index) const { return Char(this->_p[index]); }

    public:
        /**
         * @brief 获取指定字符第一次出现的位置，如果没有则返回-1。
         * @param ch 指定的字符
         * @param len 指定字符串的长度，
         *  如果使用负数（默认值），将自动计算字符串长度。
         * @return 如果字符串中不含有指定字符，返回负数。
         */
        int first_index_of(const wchar_t ch, int len = -1) const;

    public:
        /**
         * @brief 获取指定字符最后一次出现的位置,如果没有则返回-1
         * @param ch 指定的字符
         * @param len 指定字符串的长度，
         *  如果使用负数（默认值），将自动计算字符串长度。
         * @return 如果字符串中不含有指定字符，返回负数。
         */
        int last_index_of(const wchar_t ch, int len = -1) const;

    public:
        /**
         * @brief 清点指定字符在字符串中出现的次数
         * @param ch 指定的字符
         * @param len 指定字符串的长度，
         *  如果使用负数（默认值），将自动计算字符串长度。
         * @return 出现的次数
         */
        unsigned int count(const wchar_t ch, int len = -1) const;

    public:
        /**
         * @brief 获取指定的子字符串在此字符串中第一次出现的位置，
         *  如果没有则返回-1。
         * @param str 要查找的子字符串
         * @return 位置下标
         */
        int first_index_of(const wchar_t *str) const;

    public:
        /**
         * @brief  判断字符串是否为空字符串
         * @return 是返回true，否返回false。
         */
        inline bool is_empty() const { return this->_p[0] == L'0'; }

    public:
        /**
         * @brief 判断是否与指定的字符串相同，区分大小写
         * @param str 字符串
         * @return 相同返回true，不相同返回false。
         */
        bool equals(const wchar_t *str) const;

    public:
        /**
         * @brief 判断是否与指定的字符串相同，忽略大小写
         * @param str 字符串
         * @return 相同返回true，不相同返回false。
         */
        bool equals_ignore_case(const wchar_t *str) const;

    public:
        /**
         * @brief 判断是否以指定的字符串开头
         * @param str 字符串
         * @return 是返回true，否返回false。
         */
        bool is_begin_with(const wchar_t *str) const;

    public:
        /**
         * @brief 判断是否以指定的字符串结尾
         * @param str 字符串
         * @return 是返回true，否返回false。
         */
        bool is_end_with(const wchar_t *str) const;

    public:
        // 判断是否包含指定的字符串
        inline bool contains(const wchar_t *str) const { return !(this->first_index_of(str) < 0); }

        // 操作符重载
    public:
        /**
         * @brief 判断是否与指定的字符串相同，区分大小写。
         * @param str 字符串
         * @return true，false。
         */
        inline bool operator==(const wchar_t *str) const { return this->equals(str); }

    public:
        /**
         * @brief 判断是否与指定的字符串不相同，区分大小写。
         * @param str 字符串
         * @return true，false。
         */
        inline bool operator!=(const wchar_t *str) const { return !this->equals(str); }

    public:
        StringConst &operator=(const wchar_t *str)
        {
            this->_p = str;
            return *this;
        }
    };

} // namespace Pan
